import env from '@/.env'
import { showConfirm, tansParams, toast } from '@/utils/common'
import { clearAuth, getAccessToken, setAccessToken } from '@/utils/storage'
import { refreshToken } from '@/apis/login'

class Request {
  config = {
    baseUrl: env.API_BASE_URL,
    timeout: env.API_TIME_OUT,
    header: {},
  }

  requestInterceptor = null
  responseInterceptor = null

  constructor(config = {}) {
    if (config && Object.keys(config).length > 0) {
      this.requestInterceptor = config.requestInterceptor
      this.responseInterceptor = config.responseInterceptor
      this.config = Object.assign({}, this.config, config)
    }
  }

  request(method, url, config = {}) {
    config = Object.assign({}, this.config, config)
    return new Promise((resolve, reject) => {
      // 执行类实例的请求拦截器
      if (typeof this.requestInterceptor === 'function') {
        config = this.requestInterceptor(config)
      }

      let _url = this.config.baseUrl + url
      if (config.params) {
        _url += `?${tansParams(config.params)}`
      }

      uni.request({
        method,
        url: _url,
        timeout: config.timeout,
        data: config.data,
        header: { ...config.header },
      }).then(async({ data, statusCode, errMsg }) => {
        if (statusCode === 200) {
          // 执行类实例的响应拦截器
          if (typeof this.responseInterceptor === 'function') {
            data = this.responseInterceptor(data, method, url, config, resolve)
          }
          if (data === 'refreshing') {
            return
          }
          resolve(data)
        } else if (statusCode === 424) {
          toast('登录过期，请重新登录')
          clearAuth()
        } else {
          throw new Error(`${statusCode} ${errMsg}`)
        }
      }).catch((err) => {
        reject(err)
        toast(err.message)
      })
    })
  }

  get(url, config) {
    return this.request('GET', url, config)
  }

  post(url, config) {
    return this.request('POST', url, config)
  }

  put(url, config) {
    return this.request('PUT', url, config)
  }

  delete(url, config) {
    return this.request('DELETE', url, config)
  }
}

export const authRequest = new Request()

export const request = new Request({
  requestInterceptor: (config) => {
    const token = getAccessToken()
    if (token) {
      config.header.Authorization = `Bearer ${token}`
    }
    return config
  },
  responseInterceptor: (data, method, url, config, resolve) => {
    const code = data.code
    if (code === 0) {
      return data.data
    } else if (code === 401) {
      refreshToken().then((res) => {
        setAccessToken(res.data.accessToken)
        request.request(method, url, config).then(resolve) // 再次请求
      }).catch((e) => {
        showConfirm('登录状态已过期，您可以继续留在该页面，或者重新登录?').then(() => {
          clearAuth()
        })
      })

      return 'refreshing'
    } else {
      throw new Error(data.msg || '系统异常，请联系管理员')
    }
  },
})

export const workflowRequest = new Request({
  requestInterceptor: (config) => {
    const token = getAccessToken()
    if (token) {
      config.header.Authorization = `Bearer ${token}`
    }
    return config
  },
})
